home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / dvips / scanpage.c < prev    next >
C/C++ Source or Header  |  1990-01-06  |  9KB  |  233 lines

  1. /*
  2.  *   This routine scans a page for font definitions and character usage.
  3.  *   It keeps an estimate of the memory remaining in the printer, and
  4.  *   returns false when that memory is exhausted, unless scanning the
  5.  *   first page. Otherwise it returns 1 if no problems were found,
  6.  *   or 2 if it thinks the first page of a section may overflow memory.
  7.  */
  8. #include "structures.h" /* The copyright notice in that file is included too! */
  9. /*
  10.  *   These are the external routines we need.
  11.  */
  12. extern shalfword dvibyte() ;
  13. extern halfword twobytes() ;
  14. extern integer threebytes() ;
  15. extern integer signedquad() ;
  16. extern shalfword signedbyte() ;
  17. extern shalfword signedpair() ;
  18. extern integer signedtrio() ;
  19. extern void skipover() ;
  20. extern void fontdef() ;
  21. extern void predospecial() ;
  22. extern Boolean residentfont() ;
  23. extern Boolean virtualfont() ;
  24. extern void loadfont() ;
  25. extern void error() ;
  26. extern long getlong() ;
  27. /*
  28.  *   And, of course, the globals it uses.
  29.  */
  30. #ifdef DEBUG
  31. extern integer debug_flag;
  32. #endif  /* DEBUG */
  33. extern fontdesctype *curfnt ;
  34. extern fontmaptype *ffont ;
  35. extern quarterword *curpos, *curlim ;
  36. extern integer fontmem ;
  37. extern integer pagecount ;
  38. extern integer pagenum ;
  39. extern Boolean compressed ;
  40. extern char errbuf[] ;
  41. extern frametype frames[] ;
  42. /*
  43.  *   Now our scanpage routine.
  44.  */
  45. short
  46. scanpage()
  47. {
  48.    register shalfword cmd ;
  49.    register chardesctype *cd ;
  50.    register quarterword *cras ;
  51.    register long thischar ;
  52.    register integer instring = 0 ;
  53.    register fontmaptype *cfnt ;
  54.    integer fnt ;
  55.    register long pagecost = 0 ;
  56.    register frametype *frp = frames ;
  57.  
  58. #ifdef DEBUG
  59.    if (dd(D_PAGE))
  60. #ifdef SHORTINT
  61.    (void)fprintf(stderr,"Scanning page %ld\n", pagenum) ;
  62. #else   /* ~SHORTINT */
  63.    (void)fprintf(stderr,"Scanning page %d\n", pagenum) ;
  64. #endif  /* ~SHORTINT */
  65. #endif  /* DEBUG */
  66.    curfnt = NULL ;
  67.    while (1) {
  68.       switch (cmd=dvibyte()) {
  69. case 129: case 130: case 131: case 133: case 134: case 135: case 136:
  70. case 139: case 236: case 237: case 238: case 244: case 245: case 246:
  71. case 247: case 248: case 249: case 250: case 251: case 252: case 253:
  72. case 254: case 255: /* unimplemented or illegal commands */
  73.          (void)sprintf(errbuf,
  74.             "! DVI file contains unexpected command (%d)",cmd) ;
  75.          error(errbuf) ;
  76. case 132: case 137: /* eight-byte commands setrule, putrule */
  77.          (void)dvibyte() ;
  78.          (void)dvibyte() ;
  79.          (void)dvibyte() ;
  80.          (void)dvibyte() ;
  81. case 146: case 151: case 156: case 160: case 165: case 170:
  82.    /* four-byte commands right4, w4, x4, down4, y4, z4 */
  83.          (void)dvibyte() ;
  84. case 145: case 150: case 155: case 159: case 164: case 169:
  85.    /* three-byte commands right3, w3, x3, down3, y3, z3 */
  86.          (void)dvibyte() ;
  87. case 144: case 149: case 154: case 158: case 163: case 168:
  88.    /* two-byte commands right2, w2, x2, down2, y2, z2 */
  89.          (void)dvibyte() ;
  90. case 143: case 148: case 153: case 157: case 162: case 167:
  91.    /* one-byte commands right1, w1, x1, down1, y1, z1 */
  92.          (void)dvibyte() ;
  93. case 147: case 152: case 161: case 166: /* w0, x0, y0, z0 */
  94.          instring = 0 ;
  95. case 138: case 141: case 142: /* nop, push, pop */
  96.          break ;
  97. case 128: cmd = dvibyte() ; /* set1 commands drops through to setchar */
  98. default:    /* these are commands 0 (setchar0) thru 127 (setchar 127) */
  99. /*
  100.  *   We are going to approximate that each string of consecutive characters
  101.  *   requires STRINGCOST + (length of string) bytes of PostScript VM.
  102.  */
  103.          if (curfnt==NULL)
  104.             error("! Bad DVI file: no font selected") ;
  105.          if (curfnt->loaded == 2) { /* scanning a virtual font character */
  106.             frp->curp = curpos ;
  107.             frp->curl = curlim ;
  108.             frp->ff = ffont ;
  109.             frp->curf = curfnt ;
  110.             if (++frp == &frames[MAXFRAME] )
  111.                error("! virtual recursion stack overflow") ;
  112.             cd = curfnt->chardesc + cmd ;
  113.             curpos = cd->packptr + 2 ;
  114.             curlim = curpos + (256*(long)(*cd->packptr)+(*(cd->packptr+1))) ;
  115.             ffont = curfnt->localfonts ;
  116.             if (cfnt = ffont)
  117.                goto fontfound ; /* select the first local font */
  118.             curfnt = NULL ; /* unless there isn't one */
  119.          } else {
  120.             pagecost++ ;
  121.             if (! instring) {
  122.                pagecost += STRINGCOST ;
  123.                instring = 1 ;
  124.             }
  125.             if (curfnt->resfont == NULL) {
  126.                cd = curfnt->chardesc + cmd ;
  127.                if ((cd->flags & (PREVPAGE | THISPAGE)) == 0) {
  128.      /* the character hasn't been used before in the current section */
  129.                   cras = cd->packptr ;
  130.                   if (cras != NULL) {
  131.                      thischar = CHARCOST ;
  132.                      if (compressed) {
  133.                         if ((cd->flags & REPACKED) == 0) {
  134.                            repack(cd) ;
  135.                            cras = cd->packptr ;
  136.                         }
  137.                         if ((*cras & 4) == 0)
  138.                            if ((*cras & 7) == 7)
  139.                               thischar += 2 * getlong(cras + 1) * 
  140.                                      ((getlong(cras + 5) + 15) / 16) ;
  141.                            else
  142.                               thischar += 2 * cras[2] *
  143.                                           (long)((cras[1] + 15) / 16) ;
  144.                         else
  145.                            thischar += getlong(cras + 9) ;
  146.                      } else {
  147.                         if ((*cras & 4) == 0)
  148.                            if ((*cras & 7) == 7)
  149.                               thischar += 2 * getlong(cras + 1)
  150.                                           * ((getlong(cras + 5) + 15) / 16) ;
  151.                            else
  152.                               thischar += 2 * cras[2] * ((cras[1] + 15) / 16) ;
  153.                         else
  154.                            thischar += 2 * (cras[3] * 256 + cras[4]) *
  155.                               ((cras[1] * 256 + cras[2] + 15) / 16) ;
  156.                      }
  157.                      cd->flags |= THISPAGE ;
  158.                      fontmem -= thischar ;
  159.                      if (fontmem <= pagecost) {
  160.                         if (pagecount > 0)
  161.                            return(0) ;
  162.                      }
  163.                   }
  164.                }
  165.             }
  166.          }
  167.          break ;        
  168. case 171: case 172: case 173: case 174: case 175: case 176: case 177:
  169. case 178: case 179: case 180: case 181: case 182: case 183: case 184:
  170. case 185: case 186: case 187: case 188: case 189: case 190: case 191:
  171. case 192: case 193: case 194: case 195: case 196: case 197: case 198:
  172. case 199: case 200: case 201: case 202: case 203: case 204: case 205:
  173. case 206: case 207: case 208: case 209: case 210: case 211: case 212:
  174. case 213: case 214: case 215: case 216: case 217: case 218: case 219:
  175. case 220: case 221: case 222: case 223: case 224: case 225: case 226:
  176. case 227: case 228: case 229: case 230: case 231: case 232: case 233:
  177. case 234: case 235: /* font selection commands */
  178.          if (cmd < 235) fnt = cmd - 171 ; /* fntnum0 thru fntnum63 */
  179.          else fnt = dvibyte() ; /* fnt1 */
  180.          instring = 0 ;
  181.          for (cfnt=ffont; cfnt; cfnt = cfnt->next)
  182.             if (cfnt->fontnum == fnt) goto fontfound ;
  183.          error("! Bad DVI file: undefined font selected") ;
  184. fontfound: curfnt = cfnt->desc ;
  185.          if (curfnt->loaded == 0) {
  186.             if (!residentfont(curfnt))
  187.                if (!virtualfont(curfnt))
  188.                   loadfont(curfnt) ;
  189.          }
  190.          if (curfnt->psname == 0) {
  191.             if (curfnt->loaded < 2) /* virtual font costs nothing (yet) */
  192.                fontmem -= (curfnt->resfont ? PSFONTCOST : FONTCOST) ;
  193.             curfnt->psname = 1 ;
  194.             if (fontmem <= pagecost) {
  195.                if (pagecount > 0)
  196.                   return(0) ;
  197.             }
  198.          }
  199.          break ;
  200. case 239: instring = 0 ; predospecial(dvibyte()) ; break ; /* xxx1 */
  201. case 240: instring = 0 ; predospecial(twobytes()) ; break ; /* xxx2 */
  202. case 241: instring = 0 ; predospecial(threebytes()) ; break ; /* xxx3 */
  203. case 242: instring = 0 ; predospecial(signedquad()) ; break ; /* xxx4 */
  204. case 243: fontdef() ; break ; /* fntdef1 */
  205. case 140: /* eop or end of virtual char */
  206.          if (curpos) {
  207.             --frp ;
  208.             curfnt = frp->curf ;
  209.             ffont = frp->ff ;
  210.             curlim = frp->curl ;
  211.             curpos = frp->curp ;
  212.             break ;
  213.          }
  214.          goto endofpage ; /* eop */
  215.       }
  216.    }
  217. endofpage:
  218.    if (fontmem > pagecost)
  219.       return(1) ;
  220.    if (pagecount > 0)
  221.       return(0) ;
  222. #ifdef SHORTINT
  223.       (void)fprintf(stderr, "Page %ld may be too complex to print\n", pagenum) ;
  224. #else   /* ~SHORTINT */
  225.       (void)fprintf(stderr, "Page %d may be too complex to print\n", pagenum) ;
  226. #endif  /* ~SHORTINT */
  227. /*
  228.  *   This case should be rare indeed.  Even with only 200K of virtual memory,
  229.  *   at 11 bytes per char, you can have 18K characters on a page.
  230.  */
  231.    return(2) ;
  232. }
  233.